/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <hal/nrf_gpio.h>
#include <zephyr/logging/log.h>
#include "nrfx_spim.h"
#include "hal/nrf_gpio.h"
#include <hal/nrf_spim.h>
#include "display_data.h"
#include "hal/nrf_gpiote.h"
#include "nrfx_gpiote.h"

#define WORK_ON_SPI 1
#define FRAME_TIME 30
#define MAX_ROW 16
#define MAX_COL 16

#define v_din_pin NRF_GPIO_PIN_MAP(0, 29)
#define v_clk_pin NRF_GPIO_PIN_MAP(0, 30)
#define v_lat_pin NRF_GPIO_PIN_MAP(0, 31)
#define v_oe_pin NRF_GPIO_PIN_MAP(0, 28)

#define c_bk_pin NRF_GPIO_PIN_MAP(1, 11)
#define c_din_pin NRF_GPIO_PIN_MAP(1, 10)
#define c_clk_pin NRF_GPIO_PIN_MAP(1, 12)

#define KEY1_PIN NRF_GPIO_PIN_MAP(0, 11)

#define v_din_high nrf_gpio_pin_set(v_din_pin)
#define v_din_low nrf_gpio_pin_clear(v_din_pin)
#define v_clk_high nrf_gpio_pin_set(v_clk_pin)
#define v_clk_low nrf_gpio_pin_clear(v_clk_pin)
#define v_lat_high nrf_gpio_pin_set(v_lat_pin)
#define v_lat_low nrf_gpio_pin_clear(v_lat_pin)
#define v_oe_high nrf_gpio_pin_set(v_oe_pin)
#define v_oe_low nrf_gpio_pin_clear(v_oe_pin)

#define c_bk_high nrf_gpio_pin_set(c_bk_pin)
#define c_bk_low nrf_gpio_pin_clear(c_bk_pin)
#define c_din_high nrf_gpio_pin_set(c_din_pin)
#define c_din_low nrf_gpio_pin_clear(c_din_pin)
#define c_clk_high nrf_gpio_pin_set(c_clk_pin)
#define c_clk_low nrf_gpio_pin_clear(c_clk_pin)

#define us_time 1


static nrfx_spim_t spi_instance = NRFX_SPIM_INSTANCE(3);

uint16_t green_pos[16][2] = {
	{2, 0b1000000000000000},
	{2, 0b0001000000000000},
	{2, 0b0000001000000000},
	{2, 0b0000000000000010},
	{2, 0b0000000000010000},
	{2, 0b0000000010000000},
	{1, 0b0010000000000000},
	{1, 0b0000010000000000},
	{1, 0b0000000000000001},
	{1, 0b0000000000001000},
	{1, 0b0000000001000000},
	{0, 0b0100000000000000},
	{0, 0b0000100000000000},
	{0, 0b0000000100000000},
	{0, 0b0000000000000100},
	{0, 0b0000000000100000}};

uint16_t blue_pos[16][2] = {
	{2, 0b0100000000000000},
	{2, 0b0000100000000000},
	{2, 0b0000000100000000},
	{2, 0b0000000000000100},
	{2, 0b0000000000100000},
	{1, 0b1000000000000000},
	{1, 0b0001000000000000},
	{1, 0b0000001000000000},
	{1, 0b0000000000000010},
	{1, 0b0000000000010000},
	{1, 0b0000000010000000},
	{0, 0b0010000000000000},
	{0, 0b0000010000000000},
	{0, 0b0000000000000001},
	{0, 0b0000000000001000},
	{0, 0b0000000001000000}};

uint16_t red_pos[16][2] = {
	{2, 0b0010000000000000},
	{2, 0b0000010000000000},
	{2, 0b0000000000000001},
	{2, 0b0000000000001000},
	{2, 0b0000000001000000},
	{1, 0b0100000000000000},
	{1, 0b0000100000000000},
	{1, 0b0000000100000000},
	{1, 0b0000000000000100},
	{1, 0b0000000000100000},
	{0, 0b1000000000000000},
	{0, 0b0001000000000000},
	{0, 0b0000001000000000},
	{0, 0b0000000000000010},
	{0, 0b0000000000010000},
	{0, 0b0000000010000000},
};

uint8_t display_data[16][16][3] = {0};	// Array to store th`e RGB data of each LED
uint16_t display_map[16][3];			// Array to map the RGB data to the LED

int SPI_init(void)
{
	int err_code;
	nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG(v_clk_pin, v_din_pin, NRF_SPIM_PIN_NOT_CONNECTED, NRF_SPIM_PIN_NOT_CONNECTED);
	spi_config.frequency = NRF_SPIM_FREQ_8M;
	spi_config.bit_order = NRF_SPIM_BIT_ORDER_LSB_FIRST;

	err_code = nrfx_spim_init(&spi_instance, &spi_config, NULL, NULL);
	if (err_code != NRFX_SUCCESS)
	{
		printk("SPI init failed %08x \n", err_code);
	}

	return 0;
}

void SPI_write(uint16_t *data, uint16_t len)
{
	nrfx_spim_xfer_desc_t spi_tx_buff = NRFX_SPIM_XFER_TX(data, len);
	nrfx_spim_xfer(&spi_instance, &spi_tx_buff, 0);
}

void io_init(void)
{
	nrf_gpio_cfg_output(v_lat_pin);
	nrf_gpio_cfg_output(v_oe_pin);

#if WORK_ON_SPI
	SPI_init();
#else
	nrf_gpio_cfg_output(v_din_pin);
	nrf_gpio_cfg_output(v_clk_pin);

#endif

	nrf_gpio_cfg_output(c_bk_pin);
	nrf_gpio_cfg_output(c_din_pin);
	nrf_gpio_cfg_output(c_clk_pin);
}

void col_scan(uint16_t *rgb_value, uint16_t time)
{
	uint8_t i = 0;
	uint8_t j = 0;
	uint16_t rgb;

	uint8_t send_buffer[6] = {0};

	v_oe_low;
	v_lat_low;

	send_buffer[1] = rgb_value[0] >> 8;
	send_buffer[0] = rgb_value[0] & 0xff;
	send_buffer[3] = rgb_value[1] >> 8;
	send_buffer[2] = rgb_value[1] & 0xff;
	send_buffer[5] = rgb_value[2] >> 8;
	send_buffer[4] = rgb_value[2] & 0xff;

#if WORK_ON_SPI
	SPI_write(send_buffer, 6);
#else
	for (i = 0; i < 3; i++)
	{

		rgb = rgb_value[i];

		for (j = 0; j < 16; j++)
		{
			v_clk_low;
			if (rgb & 0x0001)
			{
				v_din_high;
			}
			else
			{
				v_din_low;
			}
			rgb >>= 1;

			v_clk_high;
		}
	}
#endif

	v_clk_low;
	v_lat_low;
	v_lat_high;
	v_lat_low;
	// k_usleep(time);
	v_oe_high;
}

void display_refresh(uint16_t rgb_value[16][3], uint16_t time)
{
	uint8_t i = 0;

	for (i = 0; i < 16; i++)
	{
		c_clk_high;
		c_din_low;
		col_scan(rgb_value[i], time); // 传递每一行的RGB数据
		c_clk_low;
	}
	c_din_high;
}

void display_data_clear(uint8_t display_data[16][16][3])
{
	uint8_t row = 0, col = 0;

	for(row = 0; row < 16; row++)
	{
		for(col = 0; col < 16; col++)
		{
			display_data[row][col][0] = 0;
			display_data[row][col][1] = 0;
			display_data[row][col][2] = 0;
		}

		display_map[row][0] = 0;
		display_map[row][1] = 0;
		display_map[row][2] = 0;
	}
}

void display_data_mapping(uint8_t display_data[16][16][3])
{
	uint8_t row = 0, col = 0;

	for (row = 0; row < 16; row++)
	{
		for (col = 0; col < 16; col++)
		{
			if (display_data[row][col][0] > 0)
			{
				display_data[row][col][0]--;
				display_map[row][red_pos[col][0]] |= red_pos[col][1];
			}
			else
			{
				display_map[row][red_pos[col][0]] &= ~red_pos[col][1];
			}

			if (display_data[row][col][1] > 0)
			{
				display_data[row][col][1]--;
				display_map[row][green_pos[col][0]] |= green_pos[col][1];
			}
			else
			{
				display_map[row][green_pos[col][0]] &= ~green_pos[col][1];
			}

			if (display_data[row][col][2] > 0)
			{
				display_data[row][col][2]--;
				display_map[row][blue_pos[col][0]] |= blue_pos[col][1];
			}
			else
			{
				display_map[row][blue_pos[col][0]] &= ~blue_pos[col][1];
			}
		}
	}
}

void color_compress(uint8_t data[16][16][3])
{
	uint8_t row = 0, col = 0, color = 0;

	for (row = 0; row < 16; row++)
	{
		for (col = 0; col < 16; col++)
		{
			for (color = 0; color < 3; color++)
			{
				if (data[row][col][color] > 0)
				{
					data[row][col][color] = data[row][col][color] * FRAME_TIME / 255;
				}
			}
		}
	}
}

#define SIN_DATA_SIZE 200
#define R_STEP 1
#define G_STEP 2
#define B_STEP 3
#define R_INV_STEP 6
#define G_INV_STEP 7
#define B_INV_STEP 8

uint8_t sin_data[SIN_DATA_SIZE] = 
{
	0, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 50, 54, 58, 62, 66, 70, 73,
	77, 81, 85, 88, 92, 96, 99, 103, 106, 110, 114, 117, 120, 124, 127, 131, 134,
	137, 141, 144, 147, 150, 153, 156, 160, 163, 166, 168, 171, 174, 177, 180, 182,
	185, 188, 190, 193, 195, 198, 200, 202, 205, 207, 209, 211, 213, 215, 217, 219,
	221, 223, 225, 226, 228, 230, 231, 232, 234, 235, 237, 238, 239, 240, 241, 242,
	243, 244, 245, 245, 246, 247, 247, 248, 248, 249, 249, 249, 249, 249, 249, 249,
	249, 249, 249, 249, 249, 248, 248, 247, 247, 246, 245, 245, 244, 243, 242, 241,
	240, 239, 238, 237, 235, 234, 232, 231, 230, 228, 226, 225, 223, 221, 219, 217,
	215, 213, 211, 209, 207, 205, 202, 200, 198, 195, 193, 190, 188, 185, 182, 180,
	177, 174, 171, 168, 166, 163, 160, 156, 153, 150, 147, 144, 141, 137, 134, 131,
	127, 124, 120, 117, 114, 110, 106, 103, 99, 96, 92, 88, 85, 81, 77, 73, 70, 66,
	62, 58, 54, 50, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11, 7, 3, 0};

uint8_t r_pointer = 0, g_pointer = 65, b_pointer = 135;


uint8_t image1[16][16][3] = {
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}},       
    {{255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {8, 27, 48}, {252, 194, 27}, {252, 194, 27}, {8, 27, 48}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}}, 
    {{255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}},     
    {{255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {203, 158, 33}, {252, 194, 27}, {252, 194, 27}, {224, 173, 31}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}},     
    {{255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {47, 47, 47}, {47, 47, 47}, {47, 47, 47}, {47, 47, 47}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 249, 234}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {252, 194, 27}, {255, 249, 234}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}},
    {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}}
};

uint8_t mode = 0;

void in_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
	if(pin == KEY1_PIN)
	{
		if(nrf_gpio_pin_read(KEY1_PIN) == 0)
		{
			mode++;
			if(mode > 3)
			{
				mode = 0;
			}
		}	
		

		printf("mode: %d\n", mode);
	}
}

int main(void)
{

	printf("Hello World! %s\n", CONFIG_BOARD);
	io_init();

	uint8_t row_p = 0, col_p = 0;
	uint32_t time_p = 0;

	uint16_t r = 0, g = 0, b = 0;
	uint8_t rd = 1, gd = 1, bd = 1;

	uint32_t frame = 0;

	int ret = 0;

	nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
	in_config.pull = NRF_GPIO_PIN_PULLUP;
	ret = nrfx_gpiote_in_init(KEY1_PIN, &in_config, in_pin_handler);
	if(ret != NRFX_SUCCESS)
	{
		printk("Error %d: failed to configure KEY device\n", ret);
		return;
	}
	nrfx_gpiote_in_event_enable(KEY1_PIN, true);

	while (1)
	{
		
		uint8_t set_value = 5;
		
		uint8_t row = 0, col = 0;

		if (time_p < FRAME_TIME)
		{
			time_p++;
		}
		else
		{
			time_p = 0; // 重置 time_p

			for (row = 0; row < 16; row++)
			{
				
				for (col = 0; col < 16; col++)
				{
					if(row == 0)
					{
						if ((r_pointer + col * R_INV_STEP) >= SIN_DATA_SIZE)
						{
							display_data[0][col][0] = sin_data[r_pointer + col * R_INV_STEP - SIN_DATA_SIZE] / 2;
						}
						else
						{
							display_data[0][col][0] = sin_data[r_pointer + col * R_INV_STEP] / 2;
						}

						if ((g_pointer + col * G_INV_STEP) >= SIN_DATA_SIZE)
						{
							display_data[0][col][1] = sin_data[g_pointer + col * G_INV_STEP - SIN_DATA_SIZE] / 3;
						}
						else
						{
							display_data[0][col][1] = sin_data[g_pointer + col * G_INV_STEP] / 3;
						}

						if ((b_pointer + col * B_INV_STEP) >= SIN_DATA_SIZE)
						{
							display_data[0][col][2] = sin_data[b_pointer + col * B_INV_STEP - SIN_DATA_SIZE] / 2;
						}
						else
						{
							display_data[0][col][2] = sin_data[b_pointer + col * B_INV_STEP] / 2;
						}
					}
					else
					{
						
						display_data[row][col][0] = display_data[row - 1][col][0] - set_value;
						display_data[row][col][1] = display_data[row - 1][col][1] - set_value;
						display_data[row][col][2] = display_data[row - 1][col][2] - set_value;

					}

				}
			}

			if (r_pointer < SIN_DATA_SIZE)
			{
				r_pointer += R_STEP;
			}
			else
			{
				r_pointer = r_pointer - SIN_DATA_SIZE;
			}

			if (g_pointer < SIN_DATA_SIZE)
			{
				g_pointer += G_STEP;
			}
			else
			{
				g_pointer = g_pointer - SIN_DATA_SIZE;
			}

			if (b_pointer < SIN_DATA_SIZE)
			{
				b_pointer += B_STEP;
			}
			else
			{
				b_pointer = b_pointer - SIN_DATA_SIZE;
			}

			for(row = 0; row < 16; row++)
			{
				for(col = 0; col < 16; col++)
				{
					if(mode == 0)
					{
						display_data[row][col][0] = gif1[frame][row][col][0];
						display_data[row][col][1] = gif1[frame][row][col][1] * 0.5;
						display_data[row][col][2] = gif1[frame][row][col][2] * 0.7;
					}
					

					if(mode == 1)
					{
						display_data[row][col][0] = xin_1[frame][row][col][0];
						display_data[row][col][1] = xin_1[frame][row][col][1];
						display_data[row][col][2] = xin_1[frame][row][col][2];

					}

					if(mode == 2)
					{
						display_data[row][col][0] = xin_2[frame][row][col][0];
						display_data[row][col][1] = xin_2[frame][row][col][1];
						display_data[row][col][2] = xin_2[frame][row][col][2];
					}

					if(mode == 3)
					{
						if(xin_2[frame][row][col][0] > 230 && xin_2[frame][row][col][1] > 230 && xin_2[frame][row][col][2] > 230)
						{
							display_data[row][col][0] = 0;
							display_data[row][col][1] = 0;
							display_data[row][col][2] = 0;
						}
						else
						{
							display_data[row][col][0] = xin_2[frame][row][col][0];
							display_data[row][col][1] = xin_2[frame][row][col][1];
							display_data[row][col][2] = xin_2[frame][row][col][2];
						}
					}

					
					// display_data[row][col][0] = xin_2[frame][row][col][0];
					// display_data[row][col][1] = xin_2[frame][row][col][1];
					// display_data[row][col][2] = xin_2[frame][row][col][2];
				}
			}

			if(frame == 28)
			{
				frame = 0;
			}
			else
			{
				frame++;
			}

			color_compress(display_data);
		}

		

		display_data_mapping(display_data);
		display_refresh(display_map, 1);
	}

	return 0;
}
